﻿using Raider.WinForms.Actions.Linkage;
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace Raider.WinForms.Actions
{
    /// <summary>
    /// Provides basic functionality required by <see cref="ActionManager"/>.
    /// </summary>
    public interface IAction : IDisposable, INotifyPropertyChanged
    {
        /// <summary>
        /// Gets or sets the text to be displayed on the controls linked with the action.
        /// </summary>
        string Title { get; set; }

        /// <summary>
        /// Gets or sets the value, indicating whether the action is enabled.
        /// </summary>
        bool Enabled { get; set; }

        /// <summary>
        /// Gets or sets a value that determines how the action is updated.
        /// </summary>
        ActionUpdateKind UpdateKind { get; set; }

        /// <summary>
        /// Explicitly executes the action and returns the result.
        /// </summary>
        /// <param name="argument">Optional argument of any type, that will be passed 
        /// to <see cref="ExecuteEventArgs"/>.</param>
        object DoExecute(object argument = null);

        /// <summary>
        /// Explicitly updates the action.
        /// </summary>
        /// <param name="argument">Optional argument of any type, that will be passed
        /// to <see cref="UpdateEventArgs"/>.</param>
        void DoUpdate(object argument = null);

        /// <summary>Occurs when action is going to be executed.</summary>
        event ExecutingEventHandler Executing;

        /// <summary>Occurs when action is being executed.</summary>
        event ExecuteEventHandler Execute;

        /// <summary>Occurs when action has successfully executed.</summary>
        event ExecutedEventHandler Executed;

        /// <summary>Occurs when action is going to be updated.</summary>
        event CancelEventHandler Updating;

        /// <summary>Occurs when action is being updated.</summary>
        event UpdateEventHandler Update;

        /// <summary>Occurs when action has successfully updated.</summary>
        event EventHandler Updated;

        /// <summary>Occurs when action is disposed.</summary>
        event EventHandler Disposed;
    }

    /// <summary>
    /// Represents the method that will handle the <see cref="IAction.Executing"/> event.
    /// </summary>
    public delegate void ExecutingEventHandler(object sender, ExecutingEventArgs args);

    /// <summary>
    /// Represents the method that will handle the <see cref="IAction.Execute"/> event.
    /// </summary>
    public delegate void ExecuteEventHandler(object sender, ExecuteEventArgs args);

    /// <summary>
    /// Represents the method that will handle the <see cref="IAction.Executed"/> event.
    /// </summary>
    public delegate void ExecutedEventHandler(object sender, ExecutedEventArgs args);

    /// <summary>
    /// Represents the method that will handle the <see cref="IAction.Update"/> event.
    /// </summary>
    public delegate void UpdateEventHandler(object sender, UpdateEventArgs args);

    /// <summary>
    /// Defines the way how the actions updated.
    /// </summary>
    public enum ActionUpdateKind
    {
        /// <summary>
        /// Action is updated automatically when application is in idle state.
        /// </summary>
        /// <remarks>
        /// To automatically update the action, it should be added to at least one 
        /// <see cref="ActionManager"/> with the <see cref="ActionManager.Enabled"/> property 
        /// set to <c>true</c>.
        /// </remarks>
        Automatic,
        /// <summary>
        /// Action is updated manually in the source code.
        /// </summary>
        /// <remarks>
        /// To update the action explicitly, you may use <see cref="IAction.DoUpdate"/>.
        /// </remarks>
        Manual,
    }
}
